package com.self.test;


import org.web3j.crypto.*;
import org.web3j.exceptions.MessageDecodingException;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.Transaction;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.ExecutionException;

/**
 * @author zhangwei
 * @date 2018/6/13
 */
public class MainEntrance {

//   借鉴: https://www.cnblogs.com/hongpxiaozhu/p/8574986.html

    public static BigInteger gasLimit = BigInteger.valueOf(21000L);
    public static BigInteger gasPrice = Convert.toWei(BigDecimal.ONE, Convert.Unit.GWEI).toBigInteger();

    //    ethereum: {
//        http: {
//            Main: 'https://mainnet.infura.io/mist',
//                    Ropsten: 'https://ropsten.infura.io/mist',
//                    Rinkeby: 'https://rinkeby.infura.io/mist',
//                    Kovan: 'https://kovan.infura.io/mist'
//        },
//        websockets: {
//            Main: 'wss://mainnet.infura.io/ws',
//                    Ropsten: 'wss://ropsten.infura.io/ws',
//                    Rinkeby: 'wss://rinkeby.infura.io/ws',
//                    Kovan: 'wss://kovan.infura.io/ws'
//        }
//    },
//    ipfs: {
//        gateway: 'https://ipfs.infura.io',
//                rpc: 'https://ipfs.infura.io:5001'
//    }
//    private static String ip = "http://127.0.0.1:8545/";
//    private static String ip = "https://mainnet.infura.io/mist";
//    private static String ip = "https://rinkeby.infura.io/mist";
//    private static String ip = "https://rinkeby.infura.io/parity";
    private static String ip = "http://127.0.0.1:8180";

    private static Web3j web3j;

    public static Web3j getClient() {
        if (web3j == null) {
            synchronized (MainEntrance.class) {
                if (web3j == null) {
                    web3j = Web3j.build(new HttpService(ip));
                }
            }
        }
        return web3j;
    }

    public static void main(String[] args) throws IOException, CipherException, ExecutionException, InterruptedException {

        getClient();

//        EthSyncing.Result result = getClient()
//                .ethSyncing()
//                .send()
//                .getResult();
//        System.out.println(result.isSyncing());

//        eth_getStorageAt
//        eth_getcode
//        eth_sendTransaction
//        eth_sendRawTransaction
//        eth_estimateGas
//        eth_compileLLL
//        eth_compileSerpent
//        eth_newFilter
//        eth_newBlockFilter
//        eth_newPendingTransactionFilter
//        eth_uninstallFilter
//        eth_getFilterChanges
//        eth_getFilterLogs
//        eth_getLogs
//        eth_getWork
//        eth_submitWork
//        eth_submitHashrate
//        shh_version
//        shh_getMessages

//        System.out.println(getClient()
//                .netPeerCount()
//                .send()
//                .getQuantity()
//        );

//        System.out.println(getClient()
//                .ethSendTransaction(Transaction.createEtherTransaction(
//                        "0x4639FD4520f89c2cDDAc197adE6f56D2F7Cc0595", BigInteger.ZERO, BigInteger.valueOf(21000L), BigInteger.ONE, "", BigInteger.valueOf(1000000000L))
//                )
//                .send().getTransactionHash()
//        );


//        //转账人账户地址
//        String from = "0x4639FD4520f89c2cDDAc197adE6f56D2F7Cc0595";
//        //被转人账户地址
//        String to = "0x628C685c2976320e2BEF6a55243F3066072ca0f5";
//        //转账人私钥
//        Credentials credentials = Credentials.create("xxx");

        String transactionHash = transfer();

//        web3j.pendingTransactionObservable().subscribe(t -> {
//            System.out.println(String.join("++", Lists.newArrayList(t.getCreates(), t.getFrom(), t.getTo(), t.getHash(),t.getValue().toString())));
//            System.out.println("--------------------------");
//        });
//
//        web3j.transactionObservable().filter(t->t.getHash().equals("0x978a55e123036105b7f71113b95ef1e57c2cae149619003f77aaee393669b699")).subscribe(t->{
//            System.out.println(t.getBlockNumberRaw());
//            System.out.println(t.getBlockNumber());
//            System.out.println(t.getR());
//            System.out.println(t.getS());
//            System.out.println(t);
//        });

        Transaction transaction = web3j.ethGetTransactionByHash("0x978a55e123036105b7f71113b95ef1e57c2cae149619003f77aaee393669b699").send().getTransaction().get();

        System.out.println(transaction);


//        web3j.shutdown();

    }

    public static String transfer() throws IOException, CipherException {

        String to = "0x4639FD4520f89c2cDDAc197adE6f56D2F7Cc0595";
        String from = "0x628C685c2976320e2BEF6a55243F3066072ca0f5";
        Credentials credentials = WalletUtils.loadCredentials("1234567890", new File("D:\\wallet\\UTC--2018-06-14T15-12-07.077508700Z--628c685c2976320e2bef6a55243f3066072ca0f5"));

        System.out.println(getClient().ethGetBalance(from, DefaultBlockParameterName.LATEST).send().getBalance());

        BigInteger transactionCount = BigInteger.ZERO;
        try {
            transactionCount = getClient().ethGetTransactionCount(
                    from, DefaultBlockParameterName.LATEST).send().getTransactionCount();
        } catch (MessageDecodingException e) {
        }

        System.out.println(transactionCount);

        BigInteger value = Convert.toWei("2", Convert.Unit.ETHER).toBigInteger();
        RawTransaction rawTransaction = RawTransaction.createEtherTransaction(transactionCount, gasPrice, gasLimit, to, value);

        //签名Transaction，这里要对交易做签名
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);

        //发送交易
        String transactionHash = getClient().ethSendRawTransaction(hexValue).send().getTransactionHash();

        System.out.println(transactionHash);

        return transactionHash;
    }

}